﻿using Microsoft.AspNetCore.SignalR;
using MultiAgentsClient.ChatDataStructures;
using MultiAgentsServer.Scripts.Shared.enums;
using MultiAgentsShared;

namespace MultiAgentsServer.Scripts.Hubs;

public class SignalRUserHub(IEventBus eventBus) : SignalRBaseHub(eventBus)
{
    #region ApiRequest
    public void RegisterApiRequest(Dictionary<string, object> requestParams)
    {
        var userName = requestParams.GetData<string>("userName");
        var userPassword = requestParams.GetData<string>("userPassword");
        var invitationCode = requestParams.GetData<string>("invitationCode");
        _eventBus.Publish(new RegisterCommand(Context.ConnectionId, userName, userPassword, invitationCode));
    }

    public void ChangePasswordApiRequest(Dictionary<string, object> requestParams)
    {
        var sessionId = requestParams.GetData<string>("sessionId");
        var userId = requestParams.GetData<int>("userId");
        var previousPassword = requestParams.GetData<string>("previousPassword");
        var newPassword = requestParams.GetData<string>("newPassword");
        _eventBus.Publish(new ChangePasswordCommand(Context.ConnectionId, sessionId, userId, previousPassword, newPassword));
    }

    public void LoginApiRequest(Dictionary<string, object> requestParams)
    {
        var userName = requestParams.GetData<string>("userName");
        var userPassword = requestParams.GetData<string>("userPassword");
        var isRememberMe = requestParams.GetData<bool>("isRememberMe");
        var sessionId = requestParams.GetData<string>("sessionId");
        var deviceSerialNumber = requestParams.GetData<string>("motherboardSerialNumber");
        _eventBus.Publish(new LoginCommand(Context.ConnectionId, sessionId, deviceSerialNumber, userName, userPassword, isRememberMe));
    }

    public void AutoLoginApiRequest(Dictionary<string, object> requestParams)
    {
        var sessionId = requestParams.GetData<string>("sessionId");
        var userName = requestParams.GetData<string>("userName");
        var userPasswordEncrypted = requestParams.GetData<string>("userPasswordEncrypted");
        _eventBus.Publish(new AutoLoginCommand(Context.ConnectionId, sessionId, userName, userPasswordEncrypted));
    }

    public void LogoutApiRequest(Dictionary<string, object> requestParams)
    {
        var sessionId = requestParams.GetData<string>("sessionId");
        var userId = requestParams.GetData<int>("userId");
        _eventBus.Publish(new LogoutCommand(Context.ConnectionId, sessionId, userId));
    }

    public void FetchUserdataApiRequest(Dictionary<string, object> requestParams)
    {
        var sessionId = requestParams.GetData<string>("sessionId");
        var userId = requestParams.GetData<int>("userId");
        _eventBus.Publish(new FetchUserdataCommand(Context.ConnectionId, sessionId, userId));
    }
    #endregion

    #region ApiResponse
    public static async Task LoginApiResponse(IHubContext<SignalRUserHub> hubContext, string connectionId, StatusCode status, int userId)
    {
        await hubContext.Clients.Client(connectionId).SendAsync("LoginApiResponse", status, userId);
    }

    public static async Task RegisterApiResponse(IHubContext<SignalRUserHub> hubContext, string connectionId, StatusCode status)
    {
        await hubContext.Clients.Client(connectionId).SendAsync("RegisterApiResponse", status);
    }

    public static async Task ChangePasswordApiResponse(IHubContext<SignalRUserHub> hubContext, string connectionId, StatusCode status)
    {
        await hubContext.Clients.Client(connectionId).SendAsync("ChangePasswordApiResponse", status);
    }

    public static async Task StayLoginResponse(IHubContext<SignalRUserHub> hubContext, string connectionId, string userName, string password)
    {
        await hubContext.Clients.Client(connectionId).SendAsync("StayLoginResponse", userName, password);
    }

    public static async Task FetchUserdataApiResponse(IHubContext<SignalRUserHub> hubContext, string connectionId, UserDataModel userData)
    {
        string userDataJson = userData.ConvertToJson();

        const int chunkSize = 1024 * 20; // 20 KB per chunk
        int totalSize = userDataJson.Length;
        int chunkOffset = 0;

        while (chunkOffset < totalSize)
        {
            int size = Math.Min(chunkSize, totalSize - chunkOffset);
            string strChunk = userDataJson.Substring(chunkOffset, size);
            await hubContext.Clients.Client(connectionId).SendAsync("FetchUserdataApiResponse", strChunk, chunkOffset, totalSize);
            chunkOffset += size;
        }
    }
    #endregion

    #region ConnectionRelated
    // This method is called whenever a new client connects to the hub
    public override Task OnConnectedAsync()
    {
        Debug.LogLine("Connected", ConsoleColor.Green);

        return base.OnConnectedAsync();
    }

    // This method is called whenever a client disconnects from the hub
    public override Task OnDisconnectedAsync(Exception? exception)
    {
        Debug.LogLine("DisConnected", ConsoleColor.Red);

        return base.OnDisconnectedAsync(exception);
    }
    #endregion
}
